#pragma once
#ifndef LOGGER_H
#define LOGGER_H
#include "NonCopyable.h"
#include <string>
/*
    * 定义日志的级别
    * INFO：打印一些重要的流程信息
    * ERROR：打印不影响执行的错误信息
    * FATAL：打印影响执行的错误信息
    * DEBUG：打印调试信息
*/ 
namespace mymuduo {

// 宏在程序预处理阶段完成替换，namespace 是在编译的阶段生效，所以宏与 namespace 无关，即在namespace内部和外部同样生效
// 所以不能使用名字空间来定义宏的使用范围。或者这个也是 c++ 不提倡使用宏的原因。
// 宏为多行时，每行后面先空格再加\再回车
// LOG_INFO("%s %d",arg1,arg2)
#define LOG_INFO(logmsgFormat, ...) \
    do \
    { \
        Logger& logger = Logger::instance(); \
        logger.setLogLevel(INFO); \
        char buf[1024] = {0}; \
        snprintf(buf, 1024, logmsgFormat, ##__VA_ARGS__); \
        logger.log(buf); \
    } while (0)

#define LOG_ERROR(logmsgFormat, ...) \
    do \
    { \
        Logger& logger = Logger::instance(); \
        logger.setLogLevel(ERROR); \
        char buf[1024] = {0}; \
        snprintf(buf, 1024, logmsgFormat, ##__VA_ARGS__); \
        logger.log(buf); \
    } while (0)

#define LOG_FATAL(logmsgFormat, ...) \
    do \
    { \
        Logger& logger = Logger::instance(); \
        logger.setLogLevel(FATAL); \
        char buf[1024] = {0}; \
        snprintf(buf, 1024, logmsgFormat, ##__VA_ARGS__); \
        logger.log(buf); \
        exit(-1); \
    } while (0)

#ifdef MUDEBUG
#define LOG_DEBUG(logmsgFormat, ...) \
    do \
    { \
        Logger& logger = Logger::instance(); \
        logger.setLogLevel(DEBUG); \
        char buf[1024] = {0}; \
        snprintf(buf, 1024, logmsgFormat, ##__VA_ARGS__); \
        logger.log(buf); \
    } while (0)
#else
    #define LOG_DEBUG(logmsgFormat, ...)
#endif

enum LogLever {
    INFO,
    ERROR,
    FATAL,
    DEBUG,
};

// 日志类，单例模式
class Logger : NonCopyable
{
public:
    static Logger& instance();
    void setLogLevel(int level);
    void log(std::string msg);
private:
    int log_level_;
    Logger(){}
};

} // namespace name
#endif